From cfd67186aa2804bccff15083fd3c3d19671a1c54 Mon Sep 17 00:00:00 2001 From: oliskoli Date: Mon, 30 Oct 2006 16:49:27 +0000 Subject: [PATCH] Add new feature (new option) batch mode (-b). --- main.c | 104 +++++++++++++++++++++++++++++++++++++++- xmldoc/chapters/use.xml | 26 +++++++++- 2 files changed, 127 insertions(+), 3 deletions(-) diff --git a/main.c b/main.c index b2e36f8bf..d06c0862c 100644 --- a/main.c +++ b/main.c @@ -22,11 +22,97 @@ #include "filterdefs.h" #include "cet.h" #include "cet_util.h" +#include "csv_util.h" #include "inifile.h" #include #define MYNAME "main" +typedef struct arg_stack_s { + int argn; + int argc; + char **argv; + struct arg_stack_s *prev; +} arg_stack_t; + +static arg_stack_t +*push_args(arg_stack_t *stack, const int argn, const int argc, char *argv[]) +{ + arg_stack_t *res = xmalloc(sizeof(*res)); + + res->prev = stack; + res->argn = argn; + res->argc = argc; + res->argv = (char **)argv; + + return res; +} + +static arg_stack_t +*pop_args(arg_stack_t *stack, int *argn, int *argc, char **argv[]) +{ + arg_stack_t *res; + char **argv2 = *argv; + int i; + + if (stack == NULL) fatal("main: Invalid point in time to call 'pop_args'\n"); + + for (i = 0; i < *argc; i++) + xfree(argv2[i]); + xfree(*argv); + + *argn = stack->argn; + *argc = stack->argc; + *argv = stack->argv; + + res = stack->prev; + xfree(stack); + + return res; +} + +static void +load_args(const char *filename, int *argc, char **argv[]) +{ + gbfile *fin; + char *str, *line = NULL; + int argc2; + char **argv2; + + fin = gbfopen(filename, "r", "main"); + while ((str = gbfgetstr(fin))) { + str = lrtrim(str); + if ((*str == '\0') || (*str == '#')) continue; + + if (line == NULL) line = xstrdup(str); + else { + char *tmp; + xasprintf(&tmp, "%s %s", line, str); + xfree(line); + line = tmp; + } + } + gbfclose(fin); + + argv2 = xmalloc(2 * sizeof(*argv2)); + argv2[0] = xstrdup(*argv[0]); + argc2 = 1; + + str = csv_lineparse(line, " ", "\"", 0); + while (str != NULL) { + argv2 = xrealloc(argv2, (argc2 + 2) * sizeof(*argv2)); + argv2[argc2] = xstrdup(str); + argc2++; + str = csv_lineparse(NULL, " ", "\"", 0); + } + xfree(line); + + argv2[argc2] = NULL; + + *argc = argc2; + *argv = argv2; +} + static void usage(const char *pname, int shorter ) { @@ -57,6 +143,7 @@ usage(const char *pname, int shorter ) " -r Process route information\n" " -t Process track information\n" " -w Process waypoint information [default]\n" +" -b Process command file (batch mode)\n" " -c Character set for next operation\n" " -N No smart icons on output\n" " -x filtername Invoke filter (place between inputs and output) \n" @@ -107,6 +194,7 @@ main(int argc, char *argv[]) const char *prog_name = argv[0]; /* argv is modified during processing */ queue *wpt_head_bak, *rte_head_bak, *trk_head_bak; /* #ifdef UTF8_SUPPORT */ signed int wpt_ct_bak, rte_ct_bak, trk_ct_bak; /* #ifdef UTF8_SUPPORT */ + arg_stack_t *arg_stack = NULL; global_opts.objective = wptdata; global_opts.masked_objective = NOTHINGMASK; /* this makes the default mask behaviour slightly different */ @@ -141,7 +229,8 @@ main(int argc, char *argv[]) /* * Open-code getopts since POSIX-impaired OSes don't have one. */ - for (argn = 1; argn < argc; argn++) { + argn = 1; + while (argn < argc) { char *optarg; if (argv[argn][0] != '-') { @@ -371,11 +460,24 @@ main(int argc, char *argv[]) else global_opts.inifile = inifile_init(optarg, MYNAME); break; + case 'b': + optarg = argv[argn][2] ? argv[argn]+2 : argv[++argn]; + arg_stack = push_args(arg_stack, argn, argc, argv); + load_args(optarg, &argc, &argv); + if (argc == 0) + arg_stack = pop_args(arg_stack, &argn, &argc, &argv); + else + argn = 0; + break; default: fatal("Unknown option '%s'.\n", argv[argn]); break; } + + if ((argn+1 >= argc) && (arg_stack != NULL)) + arg_stack = pop_args(arg_stack, &argn, &argc, &argv); + argn++; } /* diff --git a/xmldoc/chapters/use.xml b/xmldoc/chapters/use.xml index 6d8115094..1665a5313 100644 --- a/xmldoc/chapters/use.xml +++ b/xmldoc/chapters/use.xml @@ -232,7 +232,29 @@ merged data to multiple destinations. Will read the USB-connected Garmin and rewrite 'xxx.kml' atomically, suitable for a self-refreshing network link in Google Earth. - - + + + + Batch mode (command files) + + GPSBabel supports working with batch- (command-) files (option -b). + + + These files are ideal for holding long command lines, long file lists, complex filters + and so on. You can use all GPSBabel known options and combinations when writing + such files. Nested batch files (the '-b' option within a batch file) is supported too. + + gpsbabel -b all_my_files -o gdb -F all_my_tracks.gdb + + 'all_my_files' could look like this: + + + -i gpx + -f saxony_in_summer_2004.gpx -f austria_2005.gpx + -i gdb + -f croatia_2006.gdb + -x nukedata,waypoints,routes + -x track,pack,split,title="LOG # %Y%m%d" + -- 2.30.2